package com.microservice.common.aspect;

import com.microservice.api.user.UserServiceClient;
import com.microservice.api.common.Result;
import com.microservice.common.annotation.RequirePermission;
import com.microservice.common.context.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;

/**
 * 权限验证切面
 * 用于验证用户是否拥有访问接口所需的权限
 */
@Slf4j
@Aspect
@Component
@Order(2) // 在AuthInterceptor之后执行
public class PermissionAspect {
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    public PermissionAspect() {
        log.info("=== PermissionAspect 权限验证切面已加载 ===");
    }
    
    /**
     * 环绕通知：拦截所有带@RequirePermission注解的方法
     */
    @Around("@annotation(com.microservice.common.annotation.RequirePermission) || @within(com.microservice.common.annotation.RequirePermission)")
    public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("=== 权限验证切面被触发 ===");
        log.info("拦截方法: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 获取当前用户ID
        Long userId = UserContext.getUserId();
        if (userId == null) {
            log.warn("权限验证失败：用户未登录");
            throw new RuntimeException("权限验证失败：用户未登录");
        }
        
        // 获取方法上的@RequirePermission注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequirePermission requirePermission = method.getAnnotation(RequirePermission.class);
        
        // 如果方法上没有注解，尝试从类上获取
        if (requirePermission == null) {
            requirePermission = method.getDeclaringClass().getAnnotation(RequirePermission.class);
        }
        
        if (requirePermission == null) {
            // 没有权限注解，直接放行
            return joinPoint.proceed();
        }
        
        // 获取需要的权限
        String[] requiredPermissions = requirePermission.value();
        if (requiredPermissions == null || requiredPermissions.length == 0) {
            // 没有指定具体权限，直接放行
            return joinPoint.proceed();
        }
        
        // 从用户服务获取用户的所有权限
        Result<Set<String>> permissionsResult = userServiceClient.getUserPermissions(userId);
        if (permissionsResult == null || permissionsResult.getCode() != 200 || permissionsResult.getData() == null) {
            log.warn("获取用户权限失败，userId: {}", userId);
            throw new RuntimeException("权限验证失败：无法获取用户权限");
        }
        
        Set<String> userPermissions = permissionsResult.getData();
        
        // 验证权限
        boolean hasPermission = checkUserPermissions(userPermissions, requiredPermissions, requirePermission.logical());
        
        if (!hasPermission) {
            String username = UserContext.getUsername();
            log.warn("用户 {} (ID:{}) 权限不足，需要权限: {}, 拥有权限: {}", 
                    username, userId, Arrays.toString(requiredPermissions), userPermissions);
            throw new RuntimeException("权限不足：您没有访问该资源的权限");
        }
        
        // 权限验证通过，继续执行方法
        log.debug("用户 {} (ID:{}) 权限验证通过", UserContext.getUsername(), userId);
        return joinPoint.proceed();
    }
    
    /**
     * 检查用户权限
     * @param userPermissions 用户拥有的权限
     * @param requiredPermissions 需要的权限
     * @param logical 权限关系（AND/OR）
     * @return 是否有权限
     */
    private boolean checkUserPermissions(Set<String> userPermissions, String[] requiredPermissions, RequirePermission.Logical logical) {
        if (logical == RequirePermission.Logical.AND) {
            // AND关系：需要拥有所有权限
            for (String permission : requiredPermissions) {
                if (!userPermissions.contains(permission)) {
                    return false;
                }
            }
            return true;
        } else {
            // OR关系：拥有任一权限即可
            for (String permission : requiredPermissions) {
                if (userPermissions.contains(permission)) {
                    return true;
                }
            }
            return false;
        }
    }
}
